package com.wd.db;

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.wd.config.Config;
import com.wd.util.DESUtil;
import com.wd.util.PathUtil;
import com.wd.util.TimeWatch;

/**
 * 连接池里，对connection执行close并非真正的关闭，而是通知池回收到空闲区
 * 
 * @author long
 * @Create 2012-10-11 下午6:48:11
 * @QQ 108232706
 * @version 1.0
 * @description DBMgr
 */
public class DBMgr {

	// private Connection dbAccount;
	// public static final String DBACCOUNT = "account";
	private Connection dbWandian;
	public static final String TEXASPOKER = "texaspoker";
	// private Connection dbLog;
	// public static final String DBLOG = "log";
	// public static final int ACCOUNT = 1;
	public static final int TexasPokerDB = 2;
	// public static final int LOG = 3;
	/**
	 * 所有游戏的账号验证数据库
	 */
	public static final int AccountDB = 4;
	private Connection dbAccountDB;
	public static final String DBACCOUNTDB = "accountdb";
	public static final int ServerDB = 5;
	private Connection dbServerDB;
	public static final String DBSERVERDB = "serverdb";
	private int currentDb;
	private static Properties dbProps;
	public final int index;// 编号，对应线程池的索引
	public final ReentrantLock lock = new ReentrantLock();
	private final TimeWatch watch;
	// jdbc方式实现读写分离
	private static final Logger Log = LogManager.getLogger(DBMgr.class);

	public DBMgr(int _index) throws Throwable {
		if (!initDb(Config.getValue("db.path"))) {
			Log.error("DBMgr initDb failure");
			throw new Throwable("DBMgr initDb failure");
		}
		this.index = _index;
		watch = new TimeWatch("DBMgr");
		this.currentDb = DBMgr.TexasPokerDB;
		initDataBases();
	}

	/**
	 * 初始化几个数据库连接
	 * 
	 * @throws Throwable
	 */
	private void initDataBases() throws Throwable {
		dbWandian = initConnectionByName(TEXASPOKER);
		// dbLog = initConnectionByName(DBLOG);
		// dbAccount = initConnectionByName(DBACCOUNT);
		dbAccountDB = initConnectionByName(DBACCOUNTDB);
		dbServerDB = initConnectionByName(DBSERVERDB);
		Log.info("[DBMgr]初始化db池长度为:" + this.index);
	}

	private Connection initConnectionByName(String dbName) throws Throwable {
		String url = dbProps.getProperty(dbName + ".url");
		String user = DESUtil.decrypt(dbProps.getProperty(dbName + ".user"));
		String password = DESUtil.decrypt(dbProps.getProperty(dbName + ".password"));
		// String maxconn = dbProps.getProperty(dbName + ".maxconn", "5");
		String driver = dbProps.getProperty(dbName + ".driver");
		Log.info(String.format("[DBMgr] dbindex:%s ,dbName:[%s] 准备启用%s数据库", this.index, dbName, driver));
		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			Log.error("初始化数据库连接池错误", e);
			throw new Throwable("初始化数据库连接池错误" + e);
		}
		try {
			// 设置超时
			// DriverManager.setLoginTimeout(30);
			Log.debug("connecting....");
			watch.start();
			return DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			throw e;
		} finally {
			watch.stop("新建连接:" + dbName);
		}

	}

	private synchronized boolean initDb(String dbPath) {
		if (dbProps != null)
			return true;
		dbPath = PathUtil.getResourcePath(dbPath);
		InputStream fileinputstream = null;
		try {
			fileinputstream = new FileInputStream(dbPath);
		} catch (Exception e) {
			String msg = String.format("未找到DB配置文件%s", new Object[] { dbPath });
			Log.error(msg, e);
		}
		dbProps = new Properties();
		try {
			dbProps.load(fileinputstream);
			Log.info("[DBServer Mutil_TexasPoker:]" + dbProps.getProperty("texaspoker.url"));
		} catch (Exception e) {
			String msg = String.format("打开文件%s出错", new Object[] { dbPath });
			Log.error(msg, e);
			return false;
		}
		return true;
	}

	public Connection getDbWandian() {
		return dbWandian;
	}

	public Connection getDbAccountDB() {
		return this.dbAccountDB;
	}

	public Connection getDbServerDB() {
		return this.dbServerDB;
	}

	/**
	 * 多种数据库自由切换,DAO实现里需要访问哪个库，指定dbType类型即可.用完恢复默认库
	 * 
	 * @return
	 */
	public Connection openConn() {
		switch (this.currentDb) {

		case DBMgr.TexasPokerDB:
			return this.getDbWandian();
		case DBMgr.AccountDB:
			return this.getDbAccountDB();
		case DBMgr.ServerDB:
			return this.getDbServerDB();
			// case DBMgr.LOG:
			// return this.getDbLog();
			// case DBMgr.ACCOUNT:
			// return this.getDbAccount();
		default:
			break;
		}
		return null;

	}

	public boolean close() throws SQLException {
		close(dbWandian);
		close(dbServerDB);
		close(dbAccountDB);
		return true;
	}

	private boolean close(Connection con) throws SQLException {
		if (con != null) {
			if (!con.isClosed()) {
				con.close();
			}
		}
		return true;
	}

	public int getCurrentDb() {
		return currentDb;
	}

	public String getCurrentDbName() {
		switch (this.currentDb) {

		case DBMgr.TexasPokerDB:
			return TEXASPOKER;
		case DBMgr.AccountDB:
			return DBACCOUNTDB;
		case DBMgr.ServerDB:
			return DBSERVERDB;
			// case DBMgr.LOG:
			// return this.getDbLog();
			// case DBMgr.ACCOUNT:
			// return this.getDbAccount();
		default:
			break;
		}
		return "UnKnown";
	}

	public void setCurrentDb(int currentDb) {
		this.currentDb = currentDb;
	}
}
